<template>
  <div id="app">
    <canvas :width="screenWidth" :height="screenHeight" ref="canvas" class="canvas"></canvas>
    <a-button @click="show = !show" class="config">配置</a-button>
    <div class="operation" v-show="show">
      <a-space class="opt-button">
        <a-button @click="addNewLine" type="primary">add</a-button>
        <a-button @click="deleteData" type="danger">delete</a-button>
        <a-button @click="copyData" class="saveButton" data-clipboard-target="#saveArea">保存并复制</a-button>
      </a-space>
      <div v-for="(item, index) in sourceData" :key="index">
        <a-card>
          <h3>{{index + 1}}</h3>
          <p>起始点:（<a-input-number v-model="item[0].x" @change="handleChange" size="small"/>,<a-input-number v-model="item[0].y" @change="handleChange" size="small"/>）;</p>
          <p>终止点:（<a-input-number v-model="item[2].x" @change="handleChange" size="small"/>,<a-input-number v-model="item[2].y" @change="handleChange" size="small"/>）;</p>
          <p>角度：
            <a-space class="index-button">
              <a-input-number v-model="item[1].angel" @change="handleChange" size="small"/> 
              <a-button type="danger" icon="delete" @click="handleDeleteIndex(index)" v-if="index != 0"/>
            </a-space>
          </p>
        </a-card>
      </div>  
      <div class="sourceData" id="saveArea">{{ sourceData }}</div>
    </div>
  </div>
</template>

<script>
import Vue from 'vue';
import {Button, InputNumber, Card, Space, message} from 'ant-design-vue'
import Clipboard from 'clipboard'
import data from './mapConfig/test.json'
Vue.component(Button.name, Button);
Vue.component(InputNumber.name, InputNumber);
Vue.component(Card.name, Card);
Vue.component(Space.name,Space);
export default {
  name: "App",
  data() {
    return {
      sourceData: [
        [{x: 0, y: 0},{x: 300, y: 100, angel: 0},{x:5, y: 5 }],
      ],
      dragPoint: null,
      outsideIndex: null,
      insideIndex: null,
      screenWidth: 1920,
      screenHeight: 1080,
      rulerWidth: 20, // 每一格宽度 (1格 = 20px)
      show:true
    };
  },
  mounted() {
    this.canvas = this.$refs.canvas;
    this.ctx = this.canvas.getContext("2d");
    this.sourceData = data
    this.drawCanvas();
    this.canvas.addEventListener("mousedown", this.downEvent);
    this.canvas.addEventListener("mousemove", this.moveEvent);
    this.canvas.addEventListener("mouseup", this.upEvent);
  },
  methods: {
    drawCanvas() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

      // 基线
      this.ctx.beginPath();
      for(let j = 0; j < this.screenHeight / this.rulerWidth; j++) {
        this.ctx.moveTo(0, this.rulerWidth * j)
        this.ctx.lineTo(this.screenWidth, this.rulerWidth * j)
      }
      for(let i = 0; i < this.screenWidth / this.rulerWidth; i++) {
        this.ctx.moveTo(this.rulerWidth * i, 0)
        this.ctx.lineTo(this.rulerWidth * i, this.screenHeight)
      }
      this.ctx.lineWidth = 1
      this.ctx.strokeStyle = '#d7e0f6'
      this.ctx.stroke()

      this.ctx.strokeStyle =  '#f99'
      this.ctx.lineWidth = 2
      this.ctx.beginPath()
      this.ctx.moveTo(0,this.screenHeight/2)
      this.ctx.lineTo(this.screenWidth,this.screenHeight/2)
      this.ctx.moveTo(this.screenWidth/2,0)
      this.ctx.lineTo(this.screenWidth/2,this.screenHeight)
      this.ctx.stroke()

      // 每一条线
      this.sourceData.forEach((item,index) => {
        this.ctx.save()
        // 原点移至中心点 & y轴正方向向上
        this.ctx.translate(this.screenWidth/2, this.screenHeight/2)
        this.ctx.rotate(Math.PI);
        this.ctx.scale(-1,1);
        // 根据公式拿到控制点坐标
        let dist = Math.sqrt(
          Math.pow(item[0].x * this.rulerWidth - item[2].x * this.rulerWidth, 2) +
              Math.pow(item[0].y * this.rulerWidth - item[2].y * this.rulerWidth, 2)
          ) / 1.5
        item[1].x = (item[2].x * this.rulerWidth - dist * Math.cos((item[1].angel * Math.PI) / 180)) / this.rulerWidth
        item[1].y = (item[2].y * this.rulerWidth - dist * Math.sin((item[1].angel * Math.PI) / 180)) / this.rulerWidth
        // 每一个点 - 绘制圆
        item.forEach((v) => {
          this.ctx.save()
          if(v.angel || v.angel == 0){ 
            return false
          }
          this.ctx.fillStyle = "rgba(0,170,187,0.6)";
          this.ctx.strokeStyle = "rgba(0,170,187,0.6)";
          this.ctx.lineWidth = 0.2;
          this.ctx.beginPath();
          this.ctx.arc(v.x * this.rulerWidth, v.y * this.rulerWidth, 10, 0, 2 * Math.PI, true);
          this.ctx.restore()
          
          this.ctx.save()
          // 文字分开绘制,还原倒置文字
          this.ctx.rotate(Math.PI);
          this.ctx.scale(-1,1);
          this.ctx.font = "16px serif";
          this.ctx.fillStyle = "rgba(0,170,187,0.6)";
          this.ctx.fillText(`(${v.x}, ${v.y})`, v.x * this.rulerWidth,  - v.y * this.rulerWidth)
          this.ctx.fill();
          this.ctx.restore()
        });
        this.ctx.restore()
        // 绘制引导线
        this.ctx.strokeStyle = "#cf4520";
        this.ctx.lineWidth = 0.2;
        this.ctx.beginPath();
        this.ctx.moveTo(item[1].x * this.rulerWidth, item[1].y * this.rulerWidth);
        this.ctx.lineTo(item[0].x * this.rulerWidth, item[0].y * this.rulerWidth);
        this.ctx.stroke();
        this.ctx.beginPath();
        this.ctx.moveTo(item[1].x * this.rulerWidth, item[1].y * this.rulerWidth);
        this.ctx.lineTo(item[2].x * this.rulerWidth, item[2].y * this.rulerWidth);
        this.ctx.stroke();
        // 绘制路线
        this.ctx.strokeStyle = "#1572b5";
        this.ctx.lineWidth = 2;
        this.ctx.lineCap = "round"
        this.ctx.beginPath();
        this.ctx.moveTo(item[0].x * this.rulerWidth, item[0].y * this.rulerWidth);
        this.ctx.quadraticCurveTo(item[1].x * this.rulerWidth, item[1].y * this.rulerWidth, item[2].x * this.rulerWidth, item[2].y * this.rulerWidth);
        this.ctx.stroke();
        this.ctx.closePath();
        this.ctx.restore()
      });
      this.ctx.restore()
    },

    downEvent(e) {
      this.sourceData.forEach((item, index) => {
        item.forEach((v, i) => {
          let dx = v.x * this.rulerWidth - e.pageX + this.screenWidth/2;
          let dy = - v.y * this.rulerWidth - e.pageY + this.screenHeight/2;
          if (Math.pow(dx, 2) + Math.pow(dy, 2) < Math.pow(10, 2)) {
            this.dragPoint = v;
            this.outsideIndex = index;
            this.insideIndex = i;
            this.canvas.style.cursor = "move";
          }
        });
      });
    },

    moveEvent(e) {
      if (this.dragPoint) {
        this.sourceData[this.outsideIndex][this.insideIndex].x = (this.sourceData[this.outsideIndex][this.insideIndex].x +
          e.pageX - this.dragPoint.x - this.screenWidth/2) / this.rulerWidth;
        this.sourceData[this.outsideIndex][this.insideIndex].y = -(this.sourceData[this.outsideIndex][this.insideIndex].y +
          e.pageY - this.dragPoint.y - this.screenHeight/2) / this.rulerWidth;
        this.drawCanvas();
      }
    },

    upEvent() {
      this.dragPoint = null;
      this.outsideIndex = null;
      this.insideIndex = null;
      this.canvas.style.cursor = "default";
    },

    addNewLine() {
      // let obj = this.sourceData[this.sourceData.length - 1][2]
      let obj = JSON.parse(JSON.stringify(this.sourceData[this.sourceData.length - 1][2]))
      this.sourceData.push([
        obj,
        {
          x: this.sourceData[this.sourceData.length - 1][2].x + 5,
          y: this.sourceData[this.sourceData.length - 1][2].y + 2.5,
          angel: 0
        },
        {
          x: this.sourceData[this.sourceData.length - 1][2].x + 10,
          y: this.sourceData[this.sourceData.length - 1][2].y,
        }
      ]);
      this.drawCanvas();
    },

    // 复制到剪贴板
    copyData() {
      const clipboard = new Clipboard('.saveButton')
      clipboard.on('success', e => {
        message.info('复制成功');
        clipboard.destroy();
      })
      clipboard.on('error', e =>{
        message.info('该浏览器不支持复制');
        clipboard.destroy();
      })
      this.drawCanvas();
    },

    handleChange() {
      this.drawCanvas();
    },

    // 删除最后一个元素
    deleteData() {
      if(this.sourceData.length > 1){
        this.sourceData.pop();
      }
      this.drawCanvas();
    },
    // 删除指定元素
    handleDeleteIndex(index) {
      this.sourceData.splice(index,1);
      this.drawCanvas();
    }
  },
};
</script>

<style lang="less">
* {
  margin: 0;
  padding: 0;
}
#app {
  height: 100%;
  width: 100%;
  .config{
    position: fixed;
    right: 20px;
    top: 20px;
    z-index: 10;
  }
  .operation {
    width: 380px;
    height: 600px;
    overflow: auto;
    z-index: 9;
    position: fixed;
    right: 0;
    top: 0;
    // background: rgba(0, 0, 0, 0.1);
    backdrop-filter: blur(10px);
    box-shadow: -5px 5px 10px gray;
    padding: 20px;
    border-radius: 5px;
    margin: 20px;
    .sourceData {
      padding-bottom: 20px;
      line-height: 30px;
    }
    .opt-button {
      width: 80px;
      height: 30px;
      margin-bottom: 10px;
    }
    .index-button {
      button{
        height: 26px;
        width: 50px;
      }
    }
  }
}
</style>
